package awk.reflect.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Target;

/**
 * @author yinqiqi
 * 元注解：专门修饰注解的注解。 Udf是一个注解，但是这个注解使用在方法上还是字段上，或者是类上面？也需要定义，这就是用到了元注解。比如 @Target
 * @Target注解，是专门用来限定某个自定义注解能够被应用在哪些Java元素上面的。
 * TYPE,  类，接口（包括注解类型）或枚举的声明
 * FIELD,属性的声明
 * METHOD,方法的声明
 * PARAMETER,方法形式参数声明
 * CONSTRUCTOR,构造方法的声明
 * LOCAL_VARIABLE,局部变量声明
 * ANNOTATION_TYPE,注解类型声明
 * PACKAGE, 包的声明
 *
 * @Retention注解，即用来修饰自定义注解的生命周期。注解的生命周期有三个阶段：1、Java源文件阶段；2、编译到class文件阶段；3、运行期阶段。同样使用了RetentionPolicy枚举类型定义了三个阶段：
 * SOURCE,注解将被编译器忽略掉）
 * CLASS,注解将被编译器记录在class文件中，但在运行时不会被虚拟机保留，这是默认值
 * RUNTIME，注解将被编译器记录在class文件中，而且在运行时会被虚拟机保留，因此它们能通过反射被读取到
 * @Documented注解，是被用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。
 * @Inherited注解，是指定某个自定义注解如果写在了父类的声明部分，那么子类的声明部分也能自动拥有该注解。@Inherited注解只对那些@Target被定义为ElementType.TYPE的自定义注解起作用。
 */
@Inherited
@Target(value = {ElementType.TYPE, ElementType.METHOD})
public @interface Udf {
    /**
     * 注解类型元素（annotation type element）
     *
     * 访问修饰符必须为public，不写默认为public；
     * 该元素的类型只能是基本数据类型、String、Class、枚举类型、注解类型（体现了注解的嵌套效果）以及上述类型的一位数组；
     * 该元素的名称一般定义为名词，如果注解中只有一个元素，请把名字起为value（后面使用会带来便利操作）；
     * ()不是定义方法参数的地方，也不能在括号中定义任何参数，仅仅只是一个特殊的语法；
     * default代表默认值，值必须和第2点定义的类型一致；
     * 如果没有默认值，代表后续使用注解时必须给该类型元素赋值。
     *
     */
    public String name() default "";
}

/**
 * 如果一个注解被定义为RetentionPolicy.SOURCE，则它将被限定在Java源文件中，那么这个注解即不会参与编译也不会在运行期起任何作用，这个注解就和一个注释是一样的效果，只能被阅读Java文件的人看到；
 * 如果一个注解被定义为RetentionPolicy.CLASS，则它将被编译到Class文件中，那么编译器可以在编译时根据注解做一些处理动作，但是运行时JVM（Java虚拟机）会忽略它，我们在运行期也不能读取到；
 * 如果一个注解被定义为RetentionPolicy.RUNTIME，那么这个注解可以在运行期的加载阶段被加载到Class对象中。那么在程序运行阶段，我们可以通过反射得到这个注解，并通过判断是否有这个注解或这个注解中属性的值，从而执行不同的程序代码段。我们实际开发中的自定义注解几乎都是使用的RetentionPolicy.RUNTIME；
 * 在默认的情况下，自定义注解是使用的RetentionPolicy.CLASS。
 */
